package org.gastomuito.client;

import org.gastomuito.shared.RelatorioDespesaAnualDTO;

import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.visualization.client.AbstractDataTable;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.visualizations.corechart.Options;
import com.google.gwt.visualization.client.visualizations.corechart.PieChart;

public class DespesaPanel extends Composite implements
        ContaContabilController.DespesaDisplay {

    private static final String HTML = "<div id=\"despesaPanel\">"
            + "<h3>Informe suas despesas</h3>" + "<p id=\"valor\">"
            + "<label>$</label>" + "</p>" + "<p id=\"conta\">"
            + "<label>Conta</label>" + "</p>" + "<p id=\"repeticao\">"
            + "<label>por</label>" + "</p>" + "<p id=\"submit\">" + "</p>"
            + "<p id=\"despesaTabela\">" + "</p>" + "<p id=\"despesaGrafico\">"
            + "</p>" + "</div>";

    private SuggestBox contaField;

    private TextBox valorField;

    private ListBox repeticaoField;

    private Button adicionaDespesaButton;

    private MultiWordSuggestOracle listaConta;

    private FlexTable despesaAnualTabela;

    private HTMLPanel panel;

    public DespesaPanel() {
        valorField = new TextBox();
        repeticaoField = new ListBox();
        adicionaDespesaButton = new Button("Adicionar");
        listaConta = new MultiWordSuggestOracle();
        contaField = new SuggestBox(listaConta);
        despesaAnualTabela = new FlexTable();
        repeticaoField.addItem("mês");
        repeticaoField.addItem("semana");
        repeticaoField.addItem("ano");
        panel = new HTMLPanel(HTML);
        despesaAnualTabela.setVisible(false);
        despesaAnualTabela.addStyleName("ui-widget-content");
        despesaAnualTabela.getRowFormatter()
                .addStyleName(0, "ui-widget-header");
        contaField.setFocus(true);
        panel.add(contaField, "conta");
        panel.add(valorField, "valor");
        panel.add(repeticaoField, "repeticao");
        panel.add(adicionaDespesaButton, "submit");
        panel.add(despesaAnualTabela, "despesaTabela");
        initWidget(panel);
    }

    private void refreshFlexTable(RelatorioDespesaAnualDTO relatorio) {
        double totalPositivo = relatorio.getTotalReceitas();
        double totalNegativo = relatorio.getTotalDespesas();
        despesaAnualTabela.clear();
        int lin = 0;
        int col = 0;
        int maxCols = 4;
        despesaAnualTabela.setText(lin, (col++ % maxCols), "Valor anual");
        despesaAnualTabela.setText(lin, (col++ % maxCols), "% Despesas");
        despesaAnualTabela.setText(lin, (col++ % maxCols), "% Receitas");
        despesaAnualTabela.setText(lin, (col++ % maxCols), "Descrição");
        lin++;
        double balanco = 0.0;
        for (int i = 0; i < relatorio.getContas().length; i++, lin++) {
            balanco = relatorio.getQuantidades()[i];
            despesaAnualTabela.setText(lin, (col++ % maxCols),
                    toStringCurrency(balanco));
            despesaAnualTabela.setText(lin, (col++ % maxCols),
                    toStringPercent((balanco / totalNegativo) * 100));
            despesaAnualTabela.setText(lin, (col++ % maxCols),
                    toStringPercent((balanco / totalPositivo) * 100));
            despesaAnualTabela.setText(lin, (col++ % maxCols),
                    relatorio.getContas()[i]);
            despesaAnualTabela.getRowFormatter().addStyleName(lin,
                    "ui-widget-content");
        }
        col += 2;
        despesaAnualTabela.setText(lin, (col++ % maxCols), "Balanço");
        despesaAnualTabela.setText(lin, (col++ % maxCols),
                toStringDecimal(relatorio.getBalanco()));
    }

    private Options createOptions() {
        PieChart.PieOptions options = PieChart.PieOptions.create();
        options.setWidth(380);
        options.setHeight(380);
        options.setTitle("Gráfico de despesas anuais");
        options.set3D(true);
        return options;
    }

    private AbstractDataTable createTable(RelatorioDespesaAnualDTO result) {
        DataTable data = DataTable.create();
        int size = result.getContas().length;
        String[] contas = result.getContas();
        double[] quantidades = result.getQuantidades();
        data.addColumn(ColumnType.STRING, "Despesas");
        data.addColumn(ColumnType.NUMBER, "Despesas por receita");
        data.addRows(contas.length);
        for (int lin = 0, col = 0; lin < size; lin++) {
            data.setValue(lin, col++ % 2, contas[lin]);
            data.setValue(lin, col++ % 2, quantidades[lin]);
        }
        return data;
    }

    private String toStringDecimal(double valor) {
        return NumberFormat.getDecimalFormat().format(valor);
    }

    private String toStringPercent(double valor) {
        return NumberFormat.getPercentFormat().format(valor);
    }

    private String toStringCurrency(double valor) {
        return NumberFormat.getCurrencyFormat().format(valor);
    }

    @Override
    public HasValue<String> getValor() {
        return this.valorField;
    }

    @Override
    public HasChangeHandlers getRepeticao() {
        return this.repeticaoField;
    }

    @Override
    public HasClickHandlers getSubmit() {
        return adicionaDespesaButton;
    }

    @Override
    public HasValue<String> getConta() {
        return contaField;
    }

    @Override
    public MultiWordSuggestOracle getListaConta() {
        return listaConta;
    }

    @Override
    public void atualizar(final RelatorioDespesaAnualDTO relatorio) {
        despesaAnualTabela.setVisible(true);
        valorField.setFocus(true);
        contaField.setText("");
        valorField.setText("");
        refreshFlexTable(relatorio);
        Runnable onLoadCallback = new Runnable() {
            public void run() {
                final PieChart pie =
                        new PieChart(createTable(relatorio), createOptions());
                pie.getElement().setId("chart");
                Element elementById = panel.getElementById("chart");
                if (elementById != null) {
                    elementById.removeFromParent();
                }
                panel.add(pie, "despesaGrafico");
            }
        };
        // Load the visualization api, passing the
        // onLoadCallback to be called
        // when loading is done.
        VisualizationUtils.loadVisualizationApi(onLoadCallback,
                PieChart.PACKAGE);
    }

}
